From Martin.
authorrobertl <robertl>
Thu, 29 Apr 2010 02:16:09 +0000 (02:16 +0000)
committerrobertl <robertl>
Thu, 29 Apr 2010 02:16:09 +0000 (02:16 +0000)
garmin.c
jeeps/gps.h
jeeps/gpsapp.c
jeeps/gpsapp.h
jeeps/gpscom.c
jeeps/gpslibusb.c

index 1aeadfd16c616ac368759e337afd6707c66bc712..fd01b6f2a7fb10ffb4d300fcc5463bb97cbf6107 100644 (file)
--- a/garmin.c
+++ b/garmin.c
@@ -1070,6 +1070,7 @@ track_waypt_pr(const waypoint *wpt)
                strncpy((*cur_tx_tracklist_entry)->trk_ident, wpt->shortname, sizeof((*cur_tx_tracklist_entry)->trk_ident));
                (*cur_tx_tracklist_entry)->trk_ident[sizeof((*cur_tx_tracklist_entry)->trk_ident)-1] = 0;
        }
+       (*cur_tx_tracklist_entry)->tnew = wpt->wpt_flags.new_trkseg;
        cur_tx_tracklist_entry++;
 }
 
@@ -1077,7 +1078,7 @@ static int
 track_prepare(void)
 {
        int i;
-       int n = track_waypt_count() + track_count();
+       int32 n = track_waypt_count() + track_count();
 
        tx_tracklist = xcalloc(n, sizeof(GPS_PTrack));
        cur_tx_tracklist_entry = tx_tracklist;
@@ -1087,6 +1088,8 @@ track_prepare(void)
        my_track_count = 0;
        track_disp_all(track_hdr_pr, route_noop, track_waypt_pr);
 
+       GPS_Prepare_Track_For_Device(&tx_tracklist, &n);
+
        return n;
 }
 
index f09007908b1aaa2c6ed50b9bdce634f3219feb11..ed9d2dacb36e1d55a7ded4ace6536a17ae0c4be0 100644 (file)
@@ -249,6 +249,14 @@ typedef struct GPS_SCourse_Point
                                          * sprint = 15 */
 } GPS_OCourse_Point, *GPS_PCourse_Point;
 
+typedef struct GPS_SCourse_Limits
+{
+    uint32 max_courses;
+    uint32 max_course_laps;
+    uint32 max_course_pnt;
+    uint32 max_course_trk_pnt;
+} GPS_OCourse_Limits, *GPS_PCourse_Limits;
+
 
 typedef int (*pcb_fn) (int, struct GPS_SWay **);
 
index 81dc8e1c3f537eb7066f73be503871c5a1a498ac..d8406674705ef68b63476343ce4f36d5d8ac2ea6 100644 (file)
@@ -3688,7 +3688,7 @@ int32 GPS_A301_Get(const char *port, GPS_PTrack **trk, pcb_fn cb, int protoid)
     if(!GPS_Device_On(port, &fd))
        return gps_errno;
 
-    if ((trk_type == pD304) && gps_run_transfer != -1) {
+    if (protoid == 301 && trk_type == pD304 && gps_run_transfer != -1) {
        drain_run_cmd(fd);
     }
 
@@ -3931,7 +3931,7 @@ int32 GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n, int protoid,
     UC data[GPS_ARB_LEN];
     GPS_PPacket tra;
     GPS_PPacket rec;
-    int32 i, j;
+    int32 i;
     int32 len;
     US  method;
     US Pid_Trk_Data, Pid_Trk_Hdr, Cmnd_Transfer_Trk;
@@ -3969,42 +3969,6 @@ int32 GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n, int protoid,
        return GPS_UNSUPPORTED;
     }
 
-    /* D303/304 marks track segments with two consecutive invalid track
-     * points. Create them unless we're at the beginning of a track or there
-     * are already invalid track points (because the track was downloaded
-     * using D303/304). This needs to be done here because it will change
-     * the number of track points.
-     */
-    if (trk_type == pD303 || trk_type == pD304)
-    {
-       for(i=0;i<n;++i)
-       {
-           if (trk[i]->tnew && i>0 && !trk[i]->ishdr && !trk[i-1]->ishdr)
-           {
-               /* Create in reverse order to avoid having to readjust the
-                * index after inserting the first point.
-                */
-               for (j=i; j>=i-1; j--)
-               {
-                   if (!Is_Trackpoint_Invalid(trk[j]))
-                   {
-                       GPS_PTrack trkpt = GPS_Track_New();
-                       *trkpt = *(trk[j]);
-                       trkpt->no_latlon = 1;
-                       trkpt->alt = 1e25;
-                       trkpt->distance_populated = 0;
-                       trkpt->heartrate = 0;
-                       trkpt->cadence = 0xff;
-                       trk = xrealloc(trk, (n+1) * sizeof(GPS_PTrack));
-                       memmove(&trk[i+1], &trk[i], (n-i) * sizeof(GPS_PTrack));
-                       n++;
-                       trk[i] = trkpt;
-                   }
-               }
-           }
-       }
-    }
-
     if(protoid != 302 && !GPS_Device_On(port, &fd))
        return gps_errno;
 
@@ -7188,6 +7152,89 @@ void GPS_D1012_Send(UC *data, GPS_PCourse_Point cpt, int32 *len)
 }
 
 
+/* @func GPS_A1009_Get ******************************************************
+**
+** Get course limits from GPS
+**
+** @param [r] port [const char *] serial port
+** @param [w] limits [GPS_PCourse_Limits] course limits structure
+**
+** @return [int32] success
+************************************************************************/
+
+int32 GPS_A1009_Get(const char *port, GPS_PCourse_Limits limits)
+{
+    static UC data[2];
+    gpsdevh *fd;
+    GPS_PPacket trapkt;
+    GPS_PPacket recpkt;
+
+    if (gps_course_limits_transfer == -1)
+       return GPS_UNSUPPORTED;
+
+    if (!GPS_Device_On(port, &fd))
+       return gps_errno;
+
+    if (!(trapkt = GPS_Packet_New() ) || !(recpkt = GPS_Packet_New()))
+       return MEMORY_ERROR;
+
+    GPS_Util_Put_Short(data,
+                    COMMAND_ID[gps_device_command].Cmnd_Transfer_Course_Limits);
+    GPS_Make_Packet(&trapkt, LINK_ID[gps_link_type].Pid_Command_Data,
+                    data,2);
+    if(!GPS_Write_Packet(fd,trapkt))
+        return gps_errno;
+    if(!GPS_Get_Ack(fd, &trapkt, &recpkt))
+        return gps_errno;
+    if(!GPS_Packet_Read(fd, &recpkt))
+        return gps_errno;
+    if(!GPS_Send_Ack(fd, &trapkt, &recpkt))
+        return gps_errno;
+
+    switch(gps_course_limits_type) {
+       case pD1013:
+           GPS_D1013_Get(limits,recpkt->data);
+           break;
+       default:
+           GPS_Error("A1009_Get: Unknown Course Limits protocol %d\n",
+                     gps_course_limits_type);
+           return PROTOCOL_ERROR;
+    }
+
+    GPS_Packet_Del(&trapkt);
+    GPS_Packet_Del(&recpkt);
+
+    if (!GPS_Device_Off(fd))
+       return gps_errno;
+    return 1;
+}
+
+
+/* @func GPS_D1013_Get ******************************************************
+**
+** Convert packet D1013 to course limits structure
+**
+** @param [w] limits [GPS_PCourse_Limits] course limits structure
+** @param [r] p [UC *] packet data
+**
+** @return [void]
+************************************************************************/
+void GPS_D1013_Get(GPS_PCourse_Limits limits, UC *p)
+{
+    limits->max_courses = GPS_Util_Get_Uint(p);
+    p+=sizeof(uint32);
+
+    limits->max_course_laps = GPS_Util_Get_Uint(p);
+    p+=sizeof(uint32);
+
+    limits->max_course_pnt = GPS_Util_Get_Uint(p);
+    p+=sizeof(uint32);
+
+    limits->max_course_trk_pnt = GPS_Util_Get_Uint(p);
+    p+=sizeof(uint32);
+}
+
+
 /*
  *  It's unfortunate that these aren't constant and therefore switchable,
  *  but they really are runtime variable.  Sigh.
@@ -7331,3 +7378,54 @@ static UC Is_Trackpoint_Invalid(GPS_PTrack trk)
     return trk->no_latlon && trk->distance > 1e24 &&
            !trk->heartrate && !trk->cadence;
 }
+
+
+/* @func GPS_Prepare_Track_For_Device **********************************
+**
+** Perform device-specific adjustments on a track before upload.
+**
+** @param [r] trk [GPS_PTrack **] track
+** @param [r] n [int32 *] Number of trackpoints
+************************************************************************/
+void GPS_Prepare_Track_For_Device(GPS_PTrack **trk, int32 *n)
+{
+    int32 i, j;
+
+    /* D303/304 marks track segments with two consecutive invalid track
+     * points instead of the tnew flag. Create them unless we're at the
+     * beginning of a track or there are already invalid track points
+     * (because the track was downloaded using D303/304). This needs to be
+     * done here because it will change the number of track points.
+     */
+    if (gps_trk_type == pD303 || gps_trk_type == pD304)
+    {
+       for(i=0;i<*n;++i)
+       {
+           if ((*trk)[i]->tnew && i>0 && !(*trk)[i]->ishdr && !(*trk)[i-1]->ishdr)
+           {
+               /* Create invalid points based on the data from the point
+                * marked with tnew and the one before it.
+                */
+               for (j=i-1; j<=i; j++)
+               {
+                   if (!Is_Trackpoint_Invalid((*trk)[j]))
+                   {
+                       GPS_PTrack trkpt = GPS_Track_New();
+                       *trkpt = *((*trk)[j]);
+                       trkpt->no_latlon = 1;
+                       trkpt->alt = 1e25;
+                       trkpt->distance_populated = 0;
+                       trkpt->heartrate = 0;
+                       trkpt->cadence = 0xff;
+                       *trk = xrealloc(*trk, (*n+1) * sizeof(GPS_PTrack));
+                       memmove(&(*trk)[i+1], &(*trk)[i], (*n-i) * sizeof(GPS_PTrack));
+                       (*trk)[i] = trkpt;
+                       i++;
+                       j++;
+                       (*n)++;
+                   }
+               }
+           }
+       }
+    }
+}
index b835cfbd592be944a63404ee6e33fd700352df0f..6d1ee33cc409fd4e1a4792a701844395858bda00 100644 (file)
@@ -81,6 +81,9 @@ int32  GPS_A1008_Send(const char *port, GPS_PCourse_Point *cpt, int32 n_cpt,
 void   GPS_D1012_Get(GPS_PCourse_Point *cpt, UC *p);
 void   GPS_D1012_Send(UC *data, GPS_PCourse_Point cpt, int32 *len);
 
+int32  GPS_A1009_Get(const char *port, GPS_PCourse_Limits limits);
+void   GPS_D1013_Get(GPS_PCourse_Limits limits, UC *p);
+
 /* Unhandled documented protocols, as of:
   Garmin Device Interface Specification, May 19, 2006, Drawing Number: 001-00063-00 Rev. C
 A650  FlightBook Transfer Protocol
@@ -95,8 +98,6 @@ A1004  Fitness User Profile Transfer Protocol
        Capability A1004: D1004
 A1005  Workout Limits Transfer Protocol
        Capability A1005: D1005
-A1009  Course Limits Transfer Protocol
-       Capability A1009: D1013
 */
 /* Unimplemted and Undocumented, as listed from the following device/sw:
        GF305 3.70
@@ -113,6 +114,7 @@ Capability A1013: D1014
 
 const char * Get_Pkt_Type(US p, US d0, const char **xinfo);
 
+void GPS_Prepare_Track_For_Device(GPS_PTrack **trk, int32 *n);
 
 #endif
 
index 77f68a8b1b880d0fc5b549204d94410e80a6d606..ee80f686fe4cbb4f04cb917fb9a5a903e5e3944b 100644 (file)
@@ -793,14 +793,42 @@ int32  GPS_Command_Send_Course
                  int32 n_cpt)
 {
     gpsdevh *fd;
+    GPS_OCourse_Limits limits;
+    int32 ret;
     int32 ret_crs=0;
     int32 ret_clp=0;
     int32 ret_trk=0;
     int32 ret_cpt=0;
 
-    if(gps_course_transfer == -1)
+    if(gps_course_transfer == -1 || gps_course_limits_transfer == -1)
        return GPS_UNSUPPORTED;
 
+    /* Check course limits to make sure we're not exceeding the device's
+     * capacity.
+     */
+    switch(gps_course_limits_transfer)
+    {
+       case pA1009:
+           ret = GPS_A1009_Get(port,&limits);
+           break;
+       default:
+           GPS_Error("Send_Course: Unknown course limitsprotocol");
+           return PROTOCOL_ERROR;
+    }
+
+    if (n_crs > limits.max_courses
+        || n_clp > limits.max_course_laps
+        || n_trk > limits.max_course_trk_pnt
+        || n_cpt > limits.max_course_pnt)
+    {
+       GPS_Error("Course upload would exceed device capacity:");
+       GPS_Error("# of courses: %d, max: %d", n_crs, limits.max_courses);
+       GPS_Error("# of laps: %d, max: %d", n_clp, limits.max_course_laps);
+       GPS_Error("# of track points: %d, max: %d", n_trk, limits.max_course_trk_pnt);
+       GPS_Error("# of course points: %d, max: %d", n_cpt, limits.max_course_pnt);
+       return GPS_UNSUPPORTED;
+    }
+
     /* Initialize device communication:
      * In contrast to other transfer protocols, this has to be handled here;
      * shutting off communication in between the different parts
@@ -1165,7 +1193,7 @@ int32 GPS_Command_Send_Track_As_Course(const char *port, GPS_PTrack *trk, int32
             if (trk[trk_end+1]->ishdr)
                 break;
         if (trk_end==i)
-            trk_end=0; /* Empty track */
+            continue; /* Skip empty track */
 
         /* Create & append course */
         crs = xrealloc(crs, (n_crs+1) * sizeof(GPS_PCourse));
@@ -1192,14 +1220,16 @@ int32 GPS_Command_Send_Track_As_Course(const char *port, GPS_PTrack *trk, int32
 
     /* Append new track points */
     ctk = xrealloc(ctk, (n_ctk+n_trk) * sizeof(GPS_PTrack));
-
     first_new_ctk = n_ctk;
     for (i=0;i<n_trk;i++) {
+        if (trk[i]->ishdr && (i>=n_trk || trk[i+1]->ishdr))
+            continue;
+
         ctk[n_ctk] = GPS_Track_New();
         if (!ctk[n_ctk]) return MEMORY_ERROR;
         *ctk[n_ctk] = *trk[i];
 
-        if (ctk[n_ctk]->ishdr)
+        if (trk[i]->ishdr)
         {
             /* Index of new track, must match the track index in associated course */
             memset(ctk[n_ctk]->trk_ident, 0, sizeof(ctk[n_ctk]->trk_ident));
@@ -1219,7 +1249,7 @@ int32 GPS_Command_Send_Track_As_Course(const char *port, GPS_PTrack *trk, int32
        int min_dist_idx = 0, trk_idx = 0, min_dist_trk_idx = 0;
 
        /* Find closest track point */
-       for (j=first_new_ctk; j<first_new_ctk+n_trk; j++) {
+       for (j=first_new_ctk; j<n_ctk; j++) {
            if (ctk[j]->ishdr) {
                trk_idx = strtoul(ctk[j]->trk_ident, NULL, 0);
                continue;
index a816c38df5756495bed022e4ba9b40eff4106a39..ef82454b3f11e9de8f423c433285ea45ef108258 100644 (file)
@@ -43,8 +43,8 @@
  * coalescion into packets anyway becuase of their serial background) will
  * compensate.
  */
-#define TMOUT_I 3000 /*  Milliseconds to timeout intr pipe access. */
-#define TMOUT_B 3000 /*  Milliseconds to timeout bulk pipe access. */
+#define TMOUT_I 5000 /*  Milliseconds to timeout intr pipe access. */
+#define TMOUT_B 5000 /*  Milliseconds to timeout bulk pipe access. */
 
 typedef struct {
        struct usb_bus *busses;